package com.zhiche.wms.core.utils.qiniu;


import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.BatchStatus;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.storage.model.FileListing;
import com.qiniu.util.Auth;
import com.qiniu.util.StringUtils;
import com.zhiche.wms.core.utils.qiniu.config.QiNiuConfigurationBean;
import com.zhiche.wms.core.utils.qiniu.domain.QuniuResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.Map;

/**
 * 七牛工具类
 * https://developer.qiniu.com/kodo/sdk/1239/java
 */
@Component
public class QiNiuUtil {

    private static QiNiuConfigurationBean qiNiuConfigurationBean;

    @Autowired
    public void setQiNiuConfigurationBean(QiNiuConfigurationBean qiNiuConfigurationBean) {
        QiNiuUtil.qiNiuConfigurationBean = qiNiuConfigurationBean;
    }

    private static Auth getAuth() {
        return Auth.create(qiNiuConfigurationBean.getAccessKey(), qiNiuConfigurationBean.getSecretKey());
    }


    /**
     * 根据Bucket获取上传凭证token
     *
     * @return 返回凭证key
     */
    public static String generateSimpleUploadToken() {
        Auth auth = getAuth();
        Long invalidationTime = Long.valueOf(qiNiuConfigurationBean.getInvalidationTime());
        String bucket = qiNiuConfigurationBean.getBucket();
        return auth.uploadToken(bucket, null, invalidationTime, null);
    }

    /**
     * 根据Bucket获取上传凭证key
     *
     * @return 返回凭证key
     */
    private static String generateSimpleUploadTicket(String bucket) {
        Auth auth = getAuth();
        int invalidationTime = qiNiuConfigurationBean.getInvalidationTime();
        return auth.uploadToken(bucket, null, invalidationTime, null);
    }


    /**
     * 根据Bucket获取上传凭证key
     */
    public static String generateSimpleUploadTicket(String bucket, String key) {
        Auth auth = getAuth();
        int invalidationTime = qiNiuConfigurationBean.getInvalidationTime();
        return auth.uploadToken(bucket, key, invalidationTime, null);
    }

    /**
     * 上传文件流
     */
    public static QuniuResponse upload(byte[] data, String bucket, String key, String zoneName) throws QiniuException {
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        UploadManager uploadManager = new UploadManager(cfg);
        Response res = uploadManager.put(data, key, generateSimpleUploadTicket(bucket));
        return res.jsonToObject(QuniuResponse.class);
    }


    /**
     * 上传文件
     */
    public static QuniuResponse upload(File file, String bucket, String key, String zoneName) throws QiniuException {
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        UploadManager uploadManager = new UploadManager(cfg);
        Response res = uploadManager.put(file, key, generateSimpleUploadTicket(bucket));
        return res.jsonToObject(QuniuResponse.class);
    }

    /**
     * 获取下载地址
     *
     * @param key         上传图片key
     * @param treatMethod 处理方法
     * @return 返回值
     */
    public static String generateDownloadURL(String key, String treatMethod) {
        Auth auth = getAuth();
        long invalidationTime = Long.valueOf(qiNiuConfigurationBean.getInvalidationTime());
        String url = qiNiuConfigurationBean.getDownloadAddress();
        return auth.privateDownloadUrl(url + "/" + key + treatMethod, invalidationTime);
    }

    /**
     * 获取下载凭证
     */
    public static String generateDownloadURL(String downloadAddress, String key, String treatMethod) {
        if (StringUtils.isNullOrEmpty(key)) {
            return "";
        }
        int invalidationTime = qiNiuConfigurationBean.getInvalidationTime();
        Auth auth = getAuth();
        return auth.privateDownloadUrl(downloadAddress + "/" + key + treatMethod, invalidationTime);
    }

    /**
     * 获取图像处理后的下载凭证
     * https://developer.qiniu.com/dora/manual/3683/img-directions-for-use
     * https://developer.qiniu.com/dora/manual/1279/basic-processing-images-imageview2
     */
    public static String generateDownloadURL(String downloadAddress, String key, String treatMethod, String w, String h) {
        if (StringUtils.isNullOrEmpty(key)) {
            return "";
        }
        int invalidationTime = qiNiuConfigurationBean.getInvalidationTime();
        Auth auth = getAuth();
        if (!StringUtils.isNullOrEmpty(treatMethod)) {
            if (!StringUtils.isNullOrEmpty(w)) {
                treatMethod = treatMethod + "/w/" + w;
            }
            if (!StringUtils.isNullOrEmpty(h)) {
                treatMethod = treatMethod + "/h/" + h;
            }
            if (!StringUtils.isNullOrEmpty(treatMethod)) {
                treatMethod = "?imageView2/" + treatMethod;
            }
        }
        return auth.privateDownloadUrl(downloadAddress + "/" + key + treatMethod, invalidationTime);
    }


    /**
     * 得到文件信息
     */
    public static FileInfo getFileInfo(String key) {
        Configuration cfg = new Configuration(getZoneByName(qiNiuConfigurationBean.getZoneName()));
        FileInfo fileInfo = null;
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            fileInfo = bucketManager.stat(qiNiuConfigurationBean.getBucket(), key);
        } catch (QiniuException ex) {
            System.err.println(ex.response.toString());
        }
        return fileInfo;
    }

    /**
     * 得到文件信息
     */
    public static FileInfo getFileInfo(String zoneName, String bucket, String key) {
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        FileInfo fileInfo = null;
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            fileInfo = bucketManager.stat(bucket, key);
        } catch (QiniuException ex) {
            System.err.println(ex.response.toString());
        }
        return fileInfo;
    }

    /**
     * 修改文件类型
     */
    public static Response ChangeFile(String zoneName, String bucket, String key, String newMimeType) throws QiniuException {
        Response response = null;
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        //修改文件类型
        response = bucketManager.changeMime(bucket, key, newMimeType);
        return response;
    }

    /**
     * 复制文件副本
     * 文件的复制和文件移动其实操作一样，主要的区别是移动后源文件不存在了，而复制的结果是源文件还存在，只是多了一个新的文件副本。
     */
    public static void CopyFile(String zoneName, String fromBucket, String fromKey, String toBucket, String toKey) throws QiniuException {
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        bucketManager.copy(fromBucket, fromKey, toBucket, toKey);
    }

    /**
     * 删除空间中的文件
     */
    public static Response DeleteFile(String zoneName, String bucket, String key) throws QiniuException {
        Response response = null;
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        response = bucketManager.delete(bucket, key);
        return response;
    }


    /**
     * 设置文件的过期天数
     */
    public static Response setFileExpire(String zoneName, String bucket, String key, int intDay) throws QiniuException {
        Response response = null;
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        response = bucketManager.deleteAfterDays(bucket, key, intDay);
        return response;
    }


    /**
     * 获取空间文件列表
     *
     * @param prefix    文件名前缀
     * @param limit     每次迭代的长度限制，最大1000，推荐值 1000
     * @param delimiter 指定目录分隔符，列出所有公共前缀（模拟列出目录效果）。缺省值为空字符串
     */
    public static BucketManager.FileListIterator listFiles(String zoneName, String bucket, String prefix, int limit, String delimiter) {
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        //列举空间文件列表
        return bucketManager.createFileListIterator(bucket, prefix, limit, delimiter);
    }


    /**
     * 获取空间文件列表
     *
     * @param prefix    文件名前缀
     * @param marker    上一次列举返回的位置标记，作为本次列举的起点信息,默认值为空字符串。
     * @param limit     每次迭代的长度限制，最大1000，推荐值 1000
     * @param delimiter 指定目录分隔符，列出所有公共前缀（模拟列出目录效果）。缺省值为空字符串
     */
    public static FileListing listFiles(String zoneName, String bucket, String prefix, String marker, int limit, String delimiter) throws QiniuException {
        FileListing listFiles = null;
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        listFiles = bucketManager.listFiles(bucket, prefix, marker, limit, delimiter);
        return listFiles;
    }


    /**
     * 批量获取文件信息
     */
    public static BatchStatus[] GetFileInfo(String zoneName, String bucket, String[] keyList) throws QiniuException {
        BatchStatus[] batchStatusList = null;
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
        batchOperations.addStatOps(bucket, keyList);
        Response response = bucketManager.batch(batchOperations);
        batchStatusList = response.jsonToObject(BatchStatus[].class);
        return batchStatusList;
    }


    /**
     * 批量修改文件类型
     */
    public static BatchStatus[] ChangeFile(String zoneName, String bucket, Map<String, String> keyMimeMap) throws QiniuException {
        BatchStatus[] batchStatusList = null;
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        //单次批量请求的文件数量不得超过1000
        BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
        //添加指令
        for (Map.Entry<String, String> entry : keyMimeMap.entrySet()) {
            String key = entry.getKey();
            String newMimeType = entry.getValue();
            batchOperations.addChgmOp(bucket, key, newMimeType);
        }
        Response response = bucketManager.batch(batchOperations);
        batchStatusList = response.jsonToObject(BatchStatus[].class);
        return batchStatusList;
    }


    /**
     * 批量删除文件
     */
    public static BatchStatus[] DeleteFile(String zoneName, String bucket, String[] keyList) throws QiniuException {
        BatchStatus[] batchStatusList = null;
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        //单次批量请求的文件数量不得超过1000
        BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
        batchOperations.addDeleteOp(bucket, keyList);
        Response response = bucketManager.batch(batchOperations);
        batchStatusList = response.jsonToObject(BatchStatus[].class);
        return batchStatusList;
    }

    /**
     * 批量复制文件
     */
    public static BatchStatus[] CopyFile(String zoneName, String fromBucket, String toBucket, Map<String, String> keyMaps) throws QiniuException {
        BatchStatus[] batchStatusList = null;
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(getZoneByName(zoneName));
        //...其他参数参考类注释
        Auth auth = getAuth();
        BucketManager bucketManager = new BucketManager(auth, cfg);
        //单次批量请求的文件数量不得超过1000
        BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
        for (Map.Entry<String, String> entry : keyMaps.entrySet()) {
            String fromkey = entry.getKey();
            String toKey = entry.getValue();
            batchOperations.addCopyOp(fromBucket, fromkey, toBucket, toKey);
        }
        Response response = bucketManager.batch(batchOperations);
        batchStatusList = response.jsonToObject(BatchStatus[].class);
        return batchStatusList;
    }

    /**
     * 获取下载凭证
     */
    public static String generateDownloadTicket(String downloadAddress, String key) {
        if(StringUtils.isNullOrEmpty(key)){
            return "";
        }
        int invalidationTime = qiNiuConfigurationBean.getInvalidationTime();
        Auth auth = getAuth();
        String url = downloadAddress;
        return auth.privateDownloadUrl(url + "/" + key, invalidationTime);
    }

    public static String getDownloadUrl(String key){
        String downloadUrl = QiNiuUtil.generateDownloadTicket(qiNiuConfigurationBean.getDownloadAddress(), key);
        return downloadUrl;
    }


    /**
     * 根据区域名称得到区域
     */
    private static Zone getZoneByName(String zoneName) {
        switch (zoneName) {
            case "华北":
                return Zone.huabei();
            case "华南":
                return Zone.huanan();
            case "华东":
                return Zone.huadong();
            default:
                return Zone.autoZone();
        }
    }

}
